#ifndef DW_GRAPHICS_NODE_H
#	define DW_GRAPHICS_NODE_H

#include "graphics/color.h"
#include "graphics/boundingvolume.h"

namespace dw {
	namespace graphics {

using system::ISerializable;
using system::ISerializer;

using maths::Point3f;
using maths::Vector3f;
using maths::Vector4f;
using maths::Quaternionf;
using maths::Matrix4f;

class Renderer;
class Object;
class Camera;
class Animation;
class Model;

class Node
:	public ISerializable
{
public : //! @name Construction & Destruction
	//! @{
	Node(Node* parent = 0, const std::string& name = "");
	virtual ~Node();
	//! @}

public : //! @name Commands
	//! @{
	void attachChild(Node* node);
	void detachChild(Node* node);
	void detachChild(const unsigned i);
	void attachObject(Object* object);
	void detachObject();
	
	void lookAt(const Point3f& p);

	void update();
	void render();

	void serialize(ISerializer* serializer) const ;
	void deserialize(ISerializer* serializer);
	//! @}

public : //! @name Setup
	//! @{
	void setName(const std::string& name) { m_name = name; }
	void setColor(const Colorf& color) { m_color = color; }
	void setPosition(const Point3f& position) { m_transform.pos = Vector4f(position, 1.0f); }
	void setTransform(const Matrix4f& transform) { m_transform = transform; }
	void setParent(Node* parent) { m_parent = parent; }
	void setAnimation(Animation* animation) { m_animation = animation; }
	void setHidden(const bool hidden) { m_hidden = hidden; }
	//! @}

public : //! @name State
	//! @{
	std::string getSignature() const ;
	const std::string& getName() const { return m_name; }
	const Colorf& getColor() const { return m_color; }
	Matrix4f getViewMatrix() const ;
	const Matrix4f& getTransform() const { return m_transform; }
	const AABBox& getBoundingBox() const { return m_boundingBox; }
	const Node* getRoot() const ;
	Node* getParent() const { return m_parent; }
	uint32 getChildrenCount() const { return static_cast< uint32 >(m_children.size()); }
	Node* getChild(const unsigned i) const ;
	Node* getChild(const std::string& name);
	Object* getObject() const { return m_object; }
	Animation* getAnimation() const { return m_animation; }
	bool isHidden() const { return m_hidden; }
	bool hasObject() const { return m_object ? true : false; }
	bool hasAnimation() const { return m_animation ? true : false; }
	//! @}

protected : //! @name Types definitions
	//! @{
	typedef std::vector< Node* > NodesCollection;
	//! @}

protected : //! @name Data
	// !@{
	std::string m_name;
	Colorf m_color;
	Node* m_parent;
	NodesCollection m_children;
	Object* m_object;
	Animation* m_animation;
	bool m_hidden;
	Matrix4f m_transform;
	AABBox m_boundingBox;
	//! @}

protected:
	friend std::ostream& operator<<(std::ostream& os, const Node& node);
	friend std::istream& operator>>(std::istream& is, Node& node);
	friend std::ostream& operator<<(std::ostream& os, Model& model);
	friend std::istream& operator>>(std::istream& is, Model& model);
};
	
	} // namespace graphics
} // namespace dw

#include "graphics/node.inl" 

#endif // !DW_GRAPHICS_NODE_H
